#include "PlaceManger.h"
#include <fstream>
#include <QDebug>


PlaceManger::PlaceManger(void)
{
    strcpy(this->file,"D://Place.dat");
    this->places = new Place[300];
    this->path = NULL;
    for(int i = 0;i<50;i++)
    {
        for(int j = 0;j<50;j++)
            placeMap[i][j] = NULL;
    }
}


PlaceManger::~PlaceManger(void)
{
    delete[] this->places;
    if(path!=NULL)
        delete[] this->path;
    for(int i = 0;i<50;i++)
    {
        for(int j = 0;j<50;j++)
            if(placeMap[i][j]!=NULL)
                delete placeMap[i][j];
    }

}

void PlaceManger::Add(Place place)
{
    std::fstream out(this->file,std::ios::out|std::ios::app|std::ios::binary);
    int len = sizeof(place);
    out.write((char *)&place,len);
    out.close();
}

void PlaceManger::AddNew(Place NewPlace)
{
    std::fstream in(this->file,std::ios::in|std::ios::binary);
    int sum = 0;
    Place place;
    while(in.peek()!=EOF)
    {
        in.read((char *)&place,sizeof(place));
        if(NewPlace.getX()==place.getX()&&NewPlace.getY()==place.getY())
        {
            break;
        }
        else
        {
            sum++;
        }
    }
    in.close();
    place.setName(NewPlace.getName());
    place.setDesc(NewPlace.getDesc());
    std::fstream out(this->file,std::ios::out|std::ios::binary|std::ios::in);
    out.seekp(sum*sizeof(place));
    out.write((char *)&place,sizeof(place));
    out.close();
}



void PlaceManger::Del(char *name)
{
    std::fstream in(this->file,std::ios::in|std::ios::binary);
    Place place;
    int sum = 0;
    while(in.peek()!=EOF)
    {
        in.read((char *)&place,sizeof(place));
        if(strcmp(place.getName(),name)!=0)
        {
            this->places[sum++] = place;
        }
        else
        {
            place.setName((char *)"");
            this->places[sum++] = place;
        }
    }
    in.close();
    std::fstream out(this->file,std::ios::out|std::ios::binary);
    for(int i = 0;i<sum;i++)
    {
        out.write((char *)&this->places[i],sizeof(place));
    }
    out.close();
}

void PlaceManger::Edit(char *name, Place place)
{
    int pos = 0;
    std::fstream in(this->file,std::ios::in|std::ios::binary);
    Place temp;
    while(in.peek()!=EOF)
    {
        in.read((char *)&temp,sizeof(temp));
        if(strcmp(temp.getName(),name)==0)
        {
            break;
        }
        pos++;
    }
    in.close();
    temp.setName(place.getName());
    temp.setDesc(place.getDesc());
    std::fstream out(this->file,std::ios::in|std::ios::out|std::ios::binary);
    out.seekp(sizeof(temp)*pos);
    out.write((char *)&temp,sizeof(temp));
    out.close();
}

void PlaceManger::Edit(char *name, int num)
{
    int pos = 0;
    std::fstream in(this->file,std::ios::in|std::ios::binary);
    Place temp;
    while(in.peek()!=EOF)
    {
        in.read((char *)&temp,sizeof(temp));
        if(strcmp(temp.getName(),name)==0)
        {
            break;
        }
        pos++;
    }
    in.close();
    temp.setBicycleNum(temp.getBicycleNum()+num);
    std::fstream out(this->file,std::ios::in|std::ios::out|std::ios::binary);
    out.seekp(sizeof(temp)*pos);
    out.write((char *)&temp,sizeof(temp));
    out.close();
}

int PlaceManger::Search(char *name)
{
    std::fstream in(this->file,std::ios::in|std::ios::binary);
    Place place;
    int pos = 0;
    int flag = 0;
    while(in.peek()!=EOF)
    {
        in.read((char *)&place,sizeof(place));
        if(strcmp(place.getName(),name)==0)
        {
            flag = 1;
            break;
        }
        pos++;
    }
    if(flag)
        return pos;
    else
        return -1;
}

Place* PlaceManger::List(int &sum)
{
	sum = 0;
    std::fstream in((char *)this->file,std::ios::in|std::ios::binary);
	Place place;
	while(in.peek()!=EOF)
	{
		in.read((char *)&place,sizeof(place));
		this->places[sum++] = place;
	}
	in.close();
    return this->places;
}

Place PlaceManger::getPalceByName(char *name)
{
    std::fstream in(this->file,std::ios::in|std::ios::binary);
    Place temp;
    while(in.peek()!=EOF)
    {
        in.read((char *)&temp,sizeof(temp));
        if(strcmp(temp.getName(),name)==0)
        {
            break;
        }
    }
    in.close();
    return temp;
}

int PlaceManger::count()
{
    int sum = 0;
    std::fstream in((char *)this->file,std::ios::in|std::ios::binary);
    Place place;
    while(in.peek()!=EOF)
    {
        in.read((char *)&place,sizeof(place));
        sum++;
    }
    in.close();
    return sum;
}

int PlaceManger::realCount()
{
    int sum = 0;
    std::fstream in((char *)this->file,std::ios::in|std::ios::binary);
    Place place;
    while(in.peek()!=EOF)
    {
        in.read((char *)&place,sizeof(place));
        if(strcmp(place.getName(),"")!=0)
            sum++;
    }
    in.close();
    return sum;
}



pathNode * PlaceManger::BFS(int x1, int y1, int x2, int y2,int &length)
{
    //qDebug()<<"------------------";
    path = new pathNode[100];
    length = 0;
    struct node
    {
        int x;
        int y;
        int pre;
    }list[1000];
    int sum = 0;
    Place *places = this->List(sum);
    for(int i = 0;i < sum;i++)
    {
        placeMap[places[i].getY()][places[i].getX()] = new Place;
        *placeMap[places[i].getY()][places[i].getX()] = places[i];
    }

    int visit[50][50];
    memset(visit,0,sizeof(visit));
    int front = 0;
    int rear = 1;
    list[front] = node {x1,y1,-1};
    visit[y1][x1] = 1;
    while(front<rear)
    {
        //qDebug() <<front;
        if(list[front].x == x2&&list[front].y == y2)
        {
            //qDebug() <<list[front].x<<"  "<<list[front].y;
            while(front!=-1)
            {
                //qDebug() <<list[front].x <<list[front].y;

                path[length].x = list[front].x;
                path[length].y = list[front].y;
                front = list[front].pre;
                length ++;
            }
            break;
        }
        else
        {
            int x = list[front].x;
            int y = list[front].y;
            if(placeMap[y][x]->getUp()==1&&visit[y-1][x]==0)
            {
                visit[y-1][x] = 1;
                list[rear++] = node {x,y-1,front};    //x y-1
            }
            if(placeMap[y][x]->getDown()==1&&visit[y+1][x]==0)  //x  y+1
            {
                visit[y+1][x] = 1;
                list[rear++] = node {x,y+1,front};
            }
            if(placeMap[y][x]->getLeft()==1&&visit[y][x-1]==0)   //x-1  y
            {
                visit[y][x-1] = 1;
                list[rear++] = node {x-1,y,front};
            }
            if(placeMap[y][x]->getRight()==1&&visit[y][x+1]==0)   //x+1  y
            {
                visit[y][x+1] = 1;
                list[rear++] = node {x+1,y,front};
            }
            front++;
        }
    }
    return path;
}

gjlx *PlaceManger::GJPlan(int x1, int y1, int x2, int y2, int &length)
{
    int nodeNum = 94;
    gjlx *list = new gjlx[150];
    MyTool tool;
    gjlx *path = new gjlx[150];
    list = tool.getAllGJnode();

    int start;
    int end;
    for(int i = 0;i<nodeNum;i++)
    {
        if(list[i].x == x1&&list[i].y == y1)
        {
            start = i;
        }
        if(list[i].x == x2&&list[i].y == y2)
        {
            end = i;
        }
    }

    int len1 = 0;
    int len2 = 0;


    int i = start;
    while(i!=end)
    {
        i++;
        if(i>=nodeNum)
            i = 0;
        len1++;
    }

    i = start;
    while(i!=end)
    {
        i--;
        if(i<0)
            i = nodeNum-1;
        len2++;
    }


    if(len1<len2)
    {
        int i = start;
        while(i!=end)
        {
            path[length ++] = list[i];
            i++;
            if(i>=nodeNum)
                i = 0;
        }
        path[length ++] = list[i];
    }
    else
    {
        int i = start;
        while(i!=end)
        {
            path[length ++] = list[i];
            i--;
            if(i<0)
                i = nodeNum-1;
        }
        path[length ++] = list[i];
    }

    return path;
}

char *PlaceManger::getPlaceName(int x, int y)
{
    char *name;
    name = new char[50];
    int length = 0;
    Place *places = this->List(length);
    for(int i = 0;i<length;i++)
    {
        if(places[i].getX()==x&&places[i].getY()==y)
        {
            strcpy(name,places[i].getName());
        }
    }
    return name;
}

gjlx *PlaceManger::GJMinStopPlan(int x1, int y1, int x2, int y2, int &length)
{
    int nodeNum = 94;
    gjlx *list = new gjlx[150];
    MyTool tool;
    gjlx *path = new gjlx[150];
    list = tool.getAllGJnode();

    int start;
    int end;
    for(int i = 0;i<nodeNum;i++)
    {
        if(list[i].x == x1&&list[i].y == y1)
        {
            start = i;
        }
        if(list[i].x == x2&&list[i].y == y2)
        {
            end = i;
        }
    }
    int len1 = 0;
    int len2 = 0;
    int StopNum1 = 0;
    int StopNum2 = 0;
    int i = start;
    while(i!=end)
    {
        i++;
        if(i>=nodeNum)
            i = 0;
        if(list[i].status==0)
            StopNum1++;
        len1++;
    }
    i = start;
    while(i!=end)
    {
        i--;
        if(i<0)
            i = nodeNum-1;
        if(list[i].status==0)
            StopNum2++;
        len2++;
    }
    if(StopNum1<StopNum2||(StopNum1==StopNum2&&len1<len2))
    {
        int i = start;
        while(i!=end)
        {
            path[length ++] = list[i];
            i++;
            if(i>=nodeNum)
                i = 0;
        }
        path[length ++] = list[i];
    }
    else
    {
        int i = start;
        while(i!=end)
        {
            path[length ++] = list[i];
            i--;
            if(i<0)
                i = nodeNum-1;
        }
        path[length ++] = list[i];
    }
    return path;
}


